﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace PathFinding
{
	public class AreaViewer : Control
	{
		private List<IIntersection> _intersections = null;
		private bool _isPainting = false;

		public int IScale { get; set; }
		public int IntersectionSize { get; set; }
		public IIntersection Start { get; set; }
		public IIntersection Destination { get; set; }
		public IIntersection[] Route { get; set; }

		public AreaViewer()
		{
			_intersections = new List<IIntersection>();
			IScale = 15;
			IntersectionSize = 8;
			BackColor = Color.White;
			SetStyle(ControlStyles.UserPaint, true);
			SetStyle(ControlStyles.AllPaintingInWmPaint, true);
			SetStyle(ControlStyles.DoubleBuffer, true);
			Reset();
		}

		public void Reset()
		{
			Start = null;
			Destination = null;
			Route = null;
			foreach (IIntersection i in _intersections)
			{
				i.IsCalculated = false;
				i.Weight = 0;
			}
		}

		public void AddIntersection(IIntersection intersection)
		{
			if (intersection != null)
			{
				if ((intersection.X * IScale) > Width) Width = (intersection.X * IScale) + 20;
				if ((intersection.Y * IScale) > Height) Height = (intersection.Y * IScale) + 20;
				if (intersection != null) _intersections.Add(intersection);
			}
		}

		public void RemoveIntersection(IIntersection intersection)
		{
			_intersections.Remove(intersection);
		}

		protected override void OnClick(EventArgs e)
		{
			base.OnClick(e);
			Point p = PointToClient(Control.MousePosition);

			OnAreaClicked((p.X + (IntersectionSize / 2))  / IScale, (p.Y + (IntersectionSize / 2)) / IScale);
		}


		protected override void OnMouseMove(MouseEventArgs e)
		{
			base.OnMouseMove(e);
			//Point p = PointToClient(Control.MousePosition);

			if (Control.MouseButtons == MouseButtons.Left) OnAreaClicked((e.X + (IntersectionSize / 2)) / IScale, (e.Y + (IntersectionSize / 2)) / IScale);
		}

		protected override void  OnPaint(PaintEventArgs e)
		{
			if (!_isPainting)
			{
				_isPainting = true;
				double maxW = 1;
				if (_intersections.Count > 0)
				{
					var qry = from IIntersection i in _intersections
							  select i.Weight;
					maxW = qry.Max();
				}

				base.OnPaint(e);

				foreach (IIntersection i in _intersections)
				{
					foreach (IIntersection n in i.Neighbours)
					{
						e.Graphics.DrawLine(Pens.LightGray, i.X * IScale, i.Y * IScale, n.X * IScale, n.Y * IScale);
					}
					/*
					if (i.PreviousNode != null)
					{
						e.Graphics.DrawLine(Pens.Red, i.X * IScale, i.Y * IScale, i.PreviousNode.X * IScale, i.PreviousNode.Y * IScale);
					}
					*/

				}

				if (Destination != null && Start != null)
				{
					IIntersection curr = Destination;
					while (curr.PreviousNode != null && curr != Start)
					{
						e.Graphics.DrawLine(Pens.Black, curr.X * IScale, curr.Y * IScale, curr.PreviousNode.X * IScale, curr.PreviousNode.Y * IScale);
						curr = curr.PreviousNode;
					}
				}

				foreach (IIntersection i in _intersections)
				{
					int t = (maxW == 0) ? 255 : Convert.ToInt32(i.Weight * 255 / maxW);
					Color c = Color.FromArgb(0, t, 0);
					Brush iBrush = (i.IsCalculated) ? new SolidBrush(c) : Brushes.Red;
					if (Route != null && Route.Contains(i)) iBrush = Brushes.Pink;
					if (Start != null && i == Start) iBrush = Brushes.Yellow;
					if (Destination != null && i == Destination) iBrush = Brushes.Yellow;
					int xCoor = (i.X * IScale) - (IntersectionSize / 2);
					int yCoor = (i.Y * IScale) - (IntersectionSize / 2);
					e.Graphics.FillRectangle(iBrush, xCoor, yCoor, IntersectionSize, IntersectionSize);
					if (i.LocationName != string.Empty)
					{
						e.Graphics.DrawString(i.LocationName, Font, Brushes.Black, (float)xCoor, (float)yCoor);
					}
					//e.Graphics.DrawString(i.Weight.ToString("###"), Font, Brushes.Black, (float)xCoor, (float)yCoor);
				}
				_isPainting = false;
			}
		}
		protected override void OnMouseUp(MouseEventArgs e)
		{
			base.OnMouseUp(e);
			Refresh();
		}

		private void OnAreaClicked(int x, int y)
		{
			if (AreaClicked != null) AreaClicked(this, new AreaClickedEventArgs(x, y));
		}

		public event EventHandler<AreaClickedEventArgs> AreaClicked;
	}
}
